package com.ncs.erp.view;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Stateful;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import com.ncsc.erp.model.SysAddr01;
import com.ncsc.erp.model.HrEmpAddr;
import com.ncsc.erp.model.MmSupplierAddr;
import com.ncsc.erp.model.PcPurchaseOrderSupplierAddr;
import com.ncsc.erp.model.SdCustAddr;
import com.ncsc.erp.model.SdCustUserAddr;
import com.ncsc.erp.model.SdQuotationCustAddr;
import com.ncsc.erp.model.SdSaleOrderCustAddr;
import com.ncsc.erp.model.SysAddr02;
import com.ncsc.erp.model.SysCompanyAddr;
import java.util.Iterator;

/**
 * Backing bean for SysAddr01 entities.
 * <p>
 * This class provides CRUD functionality for all SysAddr01 entities. It focuses
 * purely on Java EE 6 standards (e.g. <tt>&#64;ConversationScoped</tt> for
 * state management, <tt>PersistenceContext</tt> for persistence,
 * <tt>CriteriaBuilder</tt> for searches) rather than introducing a CRUD framework or
 * custom base class.
 */

@Named
@Stateful
@ConversationScoped
public class SysAddr01Bean implements Serializable
{

   private static final long serialVersionUID = 1L;

   /*
    * Support creating and retrieving SysAddr01 entities
    */

   private Integer id;

   public Integer getId()
   {
      return this.id;
   }

   public void setId(Integer id)
   {
      this.id = id;
   }

   private SysAddr01 sysAddr01;

   public SysAddr01 getSysAddr01()
   {
      return this.sysAddr01;
   }

   @Inject
   private Conversation conversation;

   @PersistenceContext(type = PersistenceContextType.EXTENDED)
   private EntityManager entityManager;

   public String create()
   {

      this.conversation.begin();
      return "create?faces-redirect=true";
   }

   public void retrieve()
   {

      if (FacesContext.getCurrentInstance().isPostback())
      {
         return;
      }

      if (this.conversation.isTransient())
      {
         this.conversation.begin();
      }

      if (this.id == null)
      {
         this.sysAddr01 = this.example;
      }
      else
      {
         this.sysAddr01 = findById(getId());
      }
   }

   public SysAddr01 findById(Integer id)
   {

      return this.entityManager.find(SysAddr01.class, id);
   }

   /*
    * Support updating and deleting SysAddr01 entities
    */

   public String update()
   {
      this.conversation.end();

      try
      {
         if (this.id == null)
         {
            this.entityManager.persist(this.sysAddr01);
            return "search?faces-redirect=true";
         }
         else
         {
            this.entityManager.merge(this.sysAddr01);
            return "view?faces-redirect=true&id=" + this.sysAddr01.getAddr01No();
         }
      }
      catch (Exception e)
      {
         FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(e.getMessage()));
         return null;
      }
   }

   public String delete()
   {
      this.conversation.end();

      try
      {
         SysAddr01 deletableEntity = findById(getId());
         SysAddr02 sysAddr02 = deletableEntity.getSysAddr02();
         sysAddr02.getSysAddr01s().remove(deletableEntity);
         deletableEntity.setSysAddr02(null);
         this.entityManager.merge(sysAddr02);
         Iterator<PcPurchaseOrderSupplierAddr> iterPcPurchaseOrderSupplierAddrs = deletableEntity.getPcPurchaseOrderSupplierAddrs().iterator();
         for (; iterPcPurchaseOrderSupplierAddrs.hasNext();)
         {
            PcPurchaseOrderSupplierAddr nextInPcPurchaseOrderSupplierAddrs = iterPcPurchaseOrderSupplierAddrs.next();
            nextInPcPurchaseOrderSupplierAddrs.setSysAddr01(null);
            iterPcPurchaseOrderSupplierAddrs.remove();
            this.entityManager.merge(nextInPcPurchaseOrderSupplierAddrs);
         }
         Iterator<MmSupplierAddr> iterMmSupplierAddrs = deletableEntity.getMmSupplierAddrs().iterator();
         for (; iterMmSupplierAddrs.hasNext();)
         {
            MmSupplierAddr nextInMmSupplierAddrs = iterMmSupplierAddrs.next();
            nextInMmSupplierAddrs.setSysAddr01(null);
            iterMmSupplierAddrs.remove();
            this.entityManager.merge(nextInMmSupplierAddrs);
         }
         Iterator<SdCustUserAddr> iterSdCustUserAddrs = deletableEntity.getSdCustUserAddrs().iterator();
         for (; iterSdCustUserAddrs.hasNext();)
         {
            SdCustUserAddr nextInSdCustUserAddrs = iterSdCustUserAddrs.next();
            nextInSdCustUserAddrs.setSysAddr01(null);
            iterSdCustUserAddrs.remove();
            this.entityManager.merge(nextInSdCustUserAddrs);
         }
         Iterator<HrEmpAddr> iterHrEmpAddrs = deletableEntity.getHrEmpAddrs().iterator();
         for (; iterHrEmpAddrs.hasNext();)
         {
            HrEmpAddr nextInHrEmpAddrs = iterHrEmpAddrs.next();
            nextInHrEmpAddrs.setSysAddr01(null);
            iterHrEmpAddrs.remove();
            this.entityManager.merge(nextInHrEmpAddrs);
         }
         Iterator<SdCustAddr> iterSdCustAddrs = deletableEntity.getSdCustAddrs().iterator();
         for (; iterSdCustAddrs.hasNext();)
         {
            SdCustAddr nextInSdCustAddrs = iterSdCustAddrs.next();
            nextInSdCustAddrs.setSysAddr01(null);
            iterSdCustAddrs.remove();
            this.entityManager.merge(nextInSdCustAddrs);
         }
         Iterator<SdSaleOrderCustAddr> iterSdSaleOrderCustAddrs = deletableEntity.getSdSaleOrderCustAddrs().iterator();
         for (; iterSdSaleOrderCustAddrs.hasNext();)
         {
            SdSaleOrderCustAddr nextInSdSaleOrderCustAddrs = iterSdSaleOrderCustAddrs.next();
            nextInSdSaleOrderCustAddrs.setSysAddr01(null);
            iterSdSaleOrderCustAddrs.remove();
            this.entityManager.merge(nextInSdSaleOrderCustAddrs);
         }
         Iterator<SdQuotationCustAddr> iterSdQuotationCustAddrs = deletableEntity.getSdQuotationCustAddrs().iterator();
         for (; iterSdQuotationCustAddrs.hasNext();)
         {
            SdQuotationCustAddr nextInSdQuotationCustAddrs = iterSdQuotationCustAddrs.next();
            nextInSdQuotationCustAddrs.setSysAddr01(null);
            iterSdQuotationCustAddrs.remove();
            this.entityManager.merge(nextInSdQuotationCustAddrs);
         }
         Iterator<SysCompanyAddr> iterSysCompanyAddrs = deletableEntity.getSysCompanyAddrs().iterator();
         for (; iterSysCompanyAddrs.hasNext();)
         {
            SysCompanyAddr nextInSysCompanyAddrs = iterSysCompanyAddrs.next();
            nextInSysCompanyAddrs.setSysAddr01(null);
            iterSysCompanyAddrs.remove();
            this.entityManager.merge(nextInSysCompanyAddrs);
         }
         this.entityManager.remove(deletableEntity);
         this.entityManager.flush();
         return "search?faces-redirect=true";
      }
      catch (Exception e)
      {
         FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(e.getMessage()));
         return null;
      }
   }

   /*
    * Support searching SysAddr01 entities with pagination
    */

   private int page;
   private long count;
   private List<SysAddr01> pageItems;

   private SysAddr01 example = new SysAddr01();

   public int getPage()
   {
      return this.page;
   }

   public void setPage(int page)
   {
      this.page = page;
   }

   public int getPageSize()
   {
      return 10;
   }

   public SysAddr01 getExample()
   {
      return this.example;
   }

   public void setExample(SysAddr01 example)
   {
      this.example = example;
   }

   public void search()
   {
      this.page = 0;
   }

   public void paginate()
   {

      CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();

      // Populate this.count

      CriteriaQuery<Long> countCriteria = builder.createQuery(Long.class);
      Root<SysAddr01> root = countCriteria.from(SysAddr01.class);
      countCriteria = countCriteria.select(builder.count(root)).where(
            getSearchPredicates(root));
      this.count = this.entityManager.createQuery(countCriteria)
            .getSingleResult();

      // Populate this.pageItems

      CriteriaQuery<SysAddr01> criteria = builder.createQuery(SysAddr01.class);
      root = criteria.from(SysAddr01.class);
      TypedQuery<SysAddr01> query = this.entityManager.createQuery(criteria
            .select(root).where(getSearchPredicates(root)));
      query.setFirstResult(this.page * getPageSize()).setMaxResults(
            getPageSize());
      this.pageItems = query.getResultList();
   }

   private Predicate[] getSearchPredicates(Root<SysAddr01> root)
   {

      CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();
      List<Predicate> predicatesList = new ArrayList<Predicate>();

      int addr01No = this.example.getAddr01No();
      if (addr01No != 0)
      {
         predicatesList.add(builder.equal(root.get("addr01No"), addr01No));
      }
      SysAddr02 sysAddr02 = this.example.getSysAddr02();
      if (sysAddr02 != null)
      {
         predicatesList.add(builder.equal(root.get("sysAddr02"), sysAddr02));
      }
      String addr01Code = this.example.getAddr01Code();
      if (addr01Code != null && !"".equals(addr01Code))
      {
         predicatesList.add(builder.like(root.<String> get("addr01Code"), '%' + addr01Code + '%'));
      }
      String addr01Name = this.example.getAddr01Name();
      if (addr01Name != null && !"".equals(addr01Name))
      {
         predicatesList.add(builder.like(root.<String> get("addr01Name"), '%' + addr01Name + '%'));
      }

      return predicatesList.toArray(new Predicate[predicatesList.size()]);
   }

   public List<SysAddr01> getPageItems()
   {
      return this.pageItems;
   }

   public long getCount()
   {
      return this.count;
   }

   /*
    * Support listing and POSTing back SysAddr01 entities (e.g. from inside an
    * HtmlSelectOneMenu)
    */

   public List<SysAddr01> getAll()
   {

      CriteriaQuery<SysAddr01> criteria = this.entityManager
            .getCriteriaBuilder().createQuery(SysAddr01.class);
      return this.entityManager.createQuery(
            criteria.select(criteria.from(SysAddr01.class))).getResultList();
   }

   @Resource
   private SessionContext sessionContext;

   public Converter getConverter()
   {

      final SysAddr01Bean ejbProxy = this.sessionContext.getBusinessObject(SysAddr01Bean.class);

      return new Converter()
      {

         @Override
         public Object getAsObject(FacesContext context,
               UIComponent component, String value)
         {

            return ejbProxy.findById(Integer.valueOf(value));
         }

         @Override
         public String getAsString(FacesContext context,
               UIComponent component, Object value)
         {

            if (value == null)
            {
               return "";
            }

            return String.valueOf(((SysAddr01) value).getAddr01No());
         }
      };
   }

   /*
    * Support adding children to bidirectional, one-to-many tables
    */

   private SysAddr01 add = new SysAddr01();

   public SysAddr01 getAdd()
   {
      return this.add;
   }

   public SysAddr01 getAdded()
   {
      SysAddr01 added = this.add;
      this.add = new SysAddr01();
      return added;
   }
}